//@author A0097555N

#include "logic.h"

#define TASK_NAME	0
#define START_TIME	1
#define END_TIME	2
#define LOCATION	3
#define STATUS		4
#define NEW_NAME	5

using namespace std;

const int Logic::INVALID_INDEX = -1;

const string Logic::SPACE = " ";

const string Logic::COMMAND_ADD = "add";
const string Logic::COMMAND_HELP = "help";
const string Logic::COMMAND_DELETE = "delete";
const string Logic::COMMAND_DISPLAY = "display";
const string Logic::COMMAND_EXIT = "exit";
const string Logic::COMMAND_SEARCH = "search";
const string Logic::COMMAND_CLEAR = "clear";
const string Logic::COMMAND_UNMARK = "unmark";
const string Logic::COMMAND_UNDO = "undo";
const string Logic::COMMAND_REDO = "redo";
const string Logic::COMMAND_RENAME = "rename";
const string Logic::COMMAND_RESCHEDULE = "reschedule";
const string Logic::COMMAND_RELOCATE = "relocate";
const string Logic::COMMAND_MARK = "mark";

const string Logic::COMMAND_SHORT_ADD = "a";
const string Logic::COMMAND_SHORT_DELETE = "del";
const string Logic::COMMAND_SHORT_DISPLAY = "d";
const string Logic::COMMAND_SHORT_EXIT = "bye";
const string Logic::COMMAND_SHORT_SEARCH = "s";
const string Logic::COMMAND_SHORT_UNMARK = "um";
const string Logic::COMMAND_SHORT_UNDO = "u";
const string Logic::COMMAND_SHORT_REDO = "re";
const string Logic::COMMAND_SHORT_RENAME = "rn";
const string Logic::COMMAND_SHORT_RESCHEDULE = "rs";
const string Logic::COMMAND_SHORT_RELOCATE = "rl";
const string Logic::COMMAND_SHORT_MARK = "m";

const string Logic::COMMAND_SEARCH_OVERLOAD_EMPTY = "empty";
const string Logic::COMMAND_SEARCH_OVERLOAD_RANGE = "range";
const string Logic::COMMAND_DISPLAY_OVERLOAD_TODAY = "today";
const string Logic::COMMAND_DISPLAY_OVERLOAD_TODAY_SHORT = "tdy";


// the following Identifiers are dependent on Interpreter. 
const string Logic::IDENTIFIER_VENUE 			= "at";
const string Logic::IDENTIFIER_START_TIME 		= "from";
const string Logic::IDENTIFIER_END_TIME_TO 		= "to";
const string Logic::IDENTIFIER_END_TIME_BY 		= "by";
const string Logic::IDENTIFIER_RENAME 			= ">";

const string Logic::MESSAGE_DID_YOU_MEAN		= "Did you mean : ";
const string Logic::INVALID_COMMAND				= "invalid";		//can be any invalid string.
const string Logic::MESSAGE_TASK_RENAME			= "Task successfully renamed from ";
const string Logic::WORD_FROM					= "from";
const string Logic::WORD_TO						= "to";
const string Logic::MESSAGE_UPDATED_TASK		= "Updated task details are as follows:\n";
const string Logic::MESSAGE_TASK_ADDED			= "Details of Task Added:\n";
const string Logic::MESSAGE_DELETED				= "The following task has been deleted. Type undo for UNDO.\n";
const string Logic::MESSAGE_DID_YOU_MEAN_FOLLOW = ". If Yes, use \"1\" as the index number. Eg. To Delete use \"del 1\"."; 

Logic::Logic(){
	retrieveOldInfo();
}

Logic::~Logic(void){
}

int Logic:: retrieveOldInfo(){
	return _storage.loadFile();
}

int Logic:: Exiting(){
	return OVERALL_EXIT;
}

vector<string> Logic::getTaskDetails(string input, string *command, int* returnFlag) {
	Interpreter interObj;
	return interObj.interpret(input, command, returnFlag);
}

int Logic::execute(string inputString, string *output)
{
	int returnFlag = STATUS_CODE_SET_OVERALL::OVERALL_EXIT;
	int returnFlagFromInterpreter;

	int inputBeginIter = inputString.find_first_not_of(SPACE);

	if (inputBeginIter == std::string::npos) {
		inputString = INVALID_COMMAND;
	} else {
		inputString = inputString.substr(inputBeginIter);
	}

	string command, tempUndoCommand = "";

	vector<string> input = getTaskDetails(inputString, &command, &returnFlagFromInterpreter);

	if ((returnFlagFromInterpreter >= STATUS_CODE_SET_ERROR::ERROR_INTERPRETER_FORMAT)&&(returnFlagFromInterpreter <= STATUS_CODE_SET_ERROR::ERROR_INTERPRETER_DATETIME_INVALID)) {
		return returnFlagFromInterpreter;
	}

	COMMAND_TYPE commandType = determineCommand(command);

		switch(commandType) {
	// Undoable functions
		case ADD_TASK:			//can undo
			returnFlag = add(input, output, &tempUndoCommand);
			break;
		case DELETE_TASK:		//can undo
			returnFlag = deleter(input, output, &tempUndoCommand);
			break;
		case RENAME_TASK:		// can undo
			returnFlag = rename(input, output, &tempUndoCommand);
			break;
		case RESCHEDULE_TASK:	//can undo		
			returnFlag = reschedule(input, output, &tempUndoCommand);
			break;
		case RELOCATE_TASK:		//can undo
			returnFlag = relocate(input, output, &tempUndoCommand);
			break;
		case MARK_TASK:			//can undo
			returnFlag = markTask(input, output, &tempUndoCommand);
			break;
		case UNMARK_TASK:		// can undo
			returnFlag = unmarkTask(input, output, &tempUndoCommand);
			break;
	//Non-undoable functions
		case DISPLAY_HELP:		//no possible undo
			returnFlag = showHelp(input[TASK_NAME], output);
			break;
		case DISPLAY_TASK:		// no possible undo
			returnFlag = display(input, output, _tempStorage);
			break;
		case CLEAR_FILE:		//can't undo
			returnFlag = clear();
			break;
		case SEARCH:			//no possible undo
			returnFlag = search(input, output);
			break;
		case EXIT_FILE:			//no possible undo
			returnFlag = exitFile();
			break;
		case REDO_TASK:			//can't undo
			returnFlag = redo(output);
			break;
		case UNDO_TASK:			//to undo 'undo' call redo
			returnFlag = undo(output);
			break;
		case INVALID_ERROR:
			returnFlag = invalid();
			break;
		default:
			returnFlag = invalid();
			break;
		}

		if (tempUndoCommand != "") {
			undoCommands.push(tempUndoCommand);
			while (!redoCommands.empty()) {
				redoCommands.pop();
			}
		}

	historyCommands.push(inputString);

	_storage.saveFile();

	return returnFlag;
}

Logic::COMMAND_TYPE Logic::determineCommand(string command) {

	COMMAND_TYPE execution;
	
	if (command == COMMAND_ADD || command == COMMAND_SHORT_ADD) {
		execution = ADD_TASK;
	} else if (command == COMMAND_DELETE || command == COMMAND_SHORT_DELETE) {
		execution = DELETE_TASK;
	} else if (command == COMMAND_DISPLAY || command == COMMAND_SHORT_DISPLAY) {
		execution = DISPLAY_TASK;
	} else if (command == COMMAND_CLEAR) {
		execution = CLEAR_FILE;
	} else if (command == COMMAND_EXIT || command == COMMAND_SHORT_EXIT) {
		execution = EXIT_FILE;
	} else if (command == COMMAND_SEARCH || command == COMMAND_SHORT_SEARCH) {
		execution = SEARCH;
	} else if (command == COMMAND_RENAME || command == COMMAND_SHORT_RENAME) {
		execution = RENAME_TASK;
	} else if (command == COMMAND_RESCHEDULE || command == COMMAND_SHORT_RESCHEDULE) {
		execution = RESCHEDULE_TASK;
	} else if (command == COMMAND_RELOCATE || command == COMMAND_SHORT_RELOCATE) {
		execution = RELOCATE_TASK;
	} else if (command == COMMAND_UNDO || command == COMMAND_SHORT_UNDO) {
		execution = UNDO_TASK;
	} else if (command == COMMAND_REDO || command == COMMAND_SHORT_REDO) {
		execution = REDO_TASK;
	} else if (command == COMMAND_MARK || command == COMMAND_SHORT_MARK) {
		execution = MARK_TASK;
	} else if (command == COMMAND_UNMARK|| command == COMMAND_SHORT_UNMARK) {
		execution = UNMARK_TASK;
	} else if (command == COMMAND_HELP) {
		execution = DISPLAY_HELP;
	} else {
		execution = INVALID_ERROR;
	}
	return execution;
}

//Undoable functions

int Logic::add(vector<string> input, string *output, string *tempUndoCommand) {
	
	vector<string> taskDetails;
	int returnFlag;

	if (input[TASK_NAME] == "") {
		 returnFlag = ERROR_ADD;
	} else {
		Task *temp = new Task(input[TASK_NAME], input[START_TIME], input[END_TIME], input[LOCATION]);

		Task toBeAdded = *temp;

		returnFlag = _storage.add(toBeAdded, taskDetails);
	}
	
	if (returnFlag == SUCCESS_ADD) {
		*tempUndoCommand = (undoCommandForAdd(input[TASK_NAME]));
		*output = MESSAGE_TASK_ADDED + printTaskInfo(taskDetails);
	}

	return returnFlag;
}

	//Functions that can use index number.

int Logic::rename(vector<string> input, string *output, string *tempUndoCommand) {

	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	vector<string> taskDetailsBeforeRename, taskDetailsAfterRename;

	if (input[NEW_NAME] == "") {
		return ERROR_RENAME_NO_NEW_NAME;
	}

	int returnFlag = _storage.rename(input[NEW_NAME],input[TASK_NAME],taskDetailsBeforeRename, taskDetailsAfterRename);

	if (returnFlag == SUCCESS_RENAME) {
		*tempUndoCommand = undoCommandForRename(input[TASK_NAME], input[NEW_NAME]);
		*output = MESSAGE_TASK_RENAME + taskDetailsBeforeRename[TASK_NAME] + SPACE + WORD_TO + SPACE + taskDetailsAfterRename[TASK_NAME];
	} else if (returnFlag == ERROR_RENAME) {
		*output = callDidYouMean(input[TASK_NAME]);
	}

	return returnFlag;
}

int Logic::relocate(vector<string> input, string *output, string *tempUndoCommand) {

	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	vector<string> taskDetailsBeforeRelocate, taskDetailsAfterRelocate;

	int returnFlag = _storage.relocate(input[TASK_NAME], input[LOCATION], taskDetailsBeforeRelocate, taskDetailsAfterRelocate);

	if (returnFlag == SUCCESS_RELOCATE) {
		*tempUndoCommand = undoCommandForRelocate(input[TASK_NAME], taskDetailsBeforeRelocate[LOCATION]);
		*output = MESSAGE_UPDATED_TASK + printTaskInfo(taskDetailsAfterRelocate);
	} else if (returnFlag == ERROR_RELOCATE) {
		*output = callDidYouMean(input[TASK_NAME]);
	}

	return returnFlag;
}

 int Logic::deleter(vector<string> input, string *output, string *tempUndoCommand) {

	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}
	
	 vector<string> taskDetailsBeforeDelete;

	 int returnFlag = _storage.remove(input[TASK_NAME], taskDetailsBeforeDelete);
	 if (returnFlag == SUCCESS_REMOVE) {
		 *tempUndoCommand = (undoCommandForDelete(taskDetailsBeforeDelete));
		 *output = MESSAGE_DELETED + printTaskInfo(taskDetailsBeforeDelete);
	 } else {
		*output = callDidYouMean(input[TASK_NAME]);
	 }

	 return returnFlag;
}

int Logic::markTask(vector<string> input, string *output, string *tempUndoCommand) {

	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	int returnFlag = _storage.mark(input[TASK_NAME]);
	
	if (returnFlag == SUCCESS_MARK) {
		*tempUndoCommand = (undoCommandForMark(input[TASK_NAME]));
	} else {
		*output = callDidYouMean(input[TASK_NAME]);
	}
	return returnFlag;
}

int Logic::unmarkTask(vector<string> input, string *output, string *tempUndoCommand) {
	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	int returnFlag = _storage.unmark(input[TASK_NAME]);
	
	if (returnFlag == SUCCESS_UNMARK) { 
		*tempUndoCommand = (undoCommandForUnmark(input[TASK_NAME]));
	}else {
		*output = callDidYouMean(input[TASK_NAME]);
	}
	return returnFlag;
}

int Logic::reschedule(vector<string> input, string *output, string *tempUndoCommand) {
	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	vector<string> taskDetailsBeforeReschedule, taskDetailsAfterReschedule;
	int returnFlag = _storage.reschedule(input[TASK_NAME], input[START_TIME], input[END_TIME], taskDetailsBeforeReschedule, taskDetailsAfterReschedule);

	if (returnFlag == SUCCESS_RESCHEDULE) {
		*tempUndoCommand = (undoCommandForReschedule(taskDetailsBeforeReschedule));
		*output = MESSAGE_UPDATED_TASK + printTaskInfo(taskDetailsAfterReschedule);
	} else {
		*output = callDidYouMean(input[TASK_NAME]);
	}

	return returnFlag;
}

// non undoable functions

int Logic::search(vector<string> input, string* output) {
	vector<string> freeTimeSlotsVector;
	*output = "";
	int returnFlag = ERROR_SEARCH;

	if (input[TASK_NAME] == "") {
		 returnFlag = ERROR_SEARCH;
	} else if (input[TASK_NAME] == COMMAND_SEARCH_OVERLOAD_EMPTY) {
		returnFlag = _storage.searchEmptySlots(input[START_TIME], input[END_TIME], freeTimeSlotsVector);
		if (returnFlag == SUCCESS_SEARCH) {
			*output = printEmptySlots(freeTimeSlotsVector);  // convert vectorr to string output.
			returnFlag = SUCCESS_SEARCH_EMPTY_SLOTS;
		} 
	}
	else if (input[TASK_NAME] == COMMAND_SEARCH_OVERLOAD_RANGE) {
		returnFlag = _storage.searchInRange(input[START_TIME], input[END_TIME], _tempStorage);
		if (returnFlag == SUCCESS_SEARCH) {
			*output = displayPrinter(_tempStorage);
			returnFlag = SUCCESS_SEARCH_RANGE;
		}
	}
	else {
		returnFlag = _storage.searchKeywords(input[TASK_NAME], _tempStorage);
		if (returnFlag == SUCCESS_SEARCH) {*output = displayPrinter(_tempStorage);}
	}
	 	
	return returnFlag;
}

int Logic::showHelp(string helpType, string* output) {
	help helpObj;
	*output = helpObj.mainHelp(helpType);
	int returnFlag = SUCCESS_HELP;

	return returnFlag;
}

int Logic::clear() {
	if (historyCommands.top() != COMMAND_CLEAR) {
		return WARNING_CLEAR;
	} 

	while (!undoCommands.empty()) {
		undoCommands.pop();
	}

	while (!redoCommands.empty()) {
		redoCommands.pop();
	}

	while(!historyCommands.empty()) {
		historyCommands.pop();
	}

	return _storage.clearAll();
}

int Logic::invalid() {
	return WARNING_WRONG_INPUT;
}

string Logic::displayPrinter(vector<Task> _tempStorage) {
	
	ostringstream toUser;		

	if (_tempStorage.size() == 0) {
		toUser << "";
		return toUser.str();
	}
	
	toUser<<setw(25)<<left<< "      Task Name"<<setw(20)<<left<<"    Start Time"<<setw(20)<<left<<"    End Time" << "    Status" << endl;
	toUser << "----------------------------------------------------------------------------" << endl;
	for (int i = 0; i < _tempStorage.size(); i++){
		string tempOut = (_tempStorage[i]).outputAllTaskInfo();
		toUser << i+1 << ". "; 
		if (i < 9) {toUser << " ";}
		toUser << tempOut;
	}
	return toUser.str();
}

	//can display task by index
int Logic::display(vector<string> input, string *output, vector<Task>& _tempStorage) {
	int temp;

	int taskIndex = getIndexinInt(input[TASK_NAME]);
	assert(taskIndex <= 10);

	if (taskIndex != 0 && taskIndex <= _tempStorage.size()) {
		input[TASK_NAME] = _tempStorage[taskIndex-1].getTaskName();
	}

	string overloadCommand = input[TASK_NAME];
	*output = "";

	if (overloadCommand == COMMAND_DISPLAY_OVERLOAD_TODAY||overloadCommand == COMMAND_DISPLAY_OVERLOAD_TODAY_SHORT) {
		temp = _storage.displayToday(_tempStorage);
		*output = displayPrinter(_tempStorage);
	} else {
		vector<string> taskDetailsVector;
		temp = _storage.searchTaskName(overloadCommand, taskDetailsVector);

		if(temp == SUCCESS_SEARCH) {
			*output = printTaskInfo(taskDetailsVector);
		} else {
			temp = _storage.displayAll(_tempStorage);
			*output = displayPrinter(_tempStorage);
			if (overloadCommand != "") {
				temp = WARNING_DISPLAY_TASK;
			}
		}
	}
	
	return temp;
}

int Logic::exitFile() {
	return OVERALL_EXIT; 
}

string Logic::printEmptySlots(vector<string> emptySlotVector) {

	int size = emptySlotVector.size();
	int numberEmptySlots = size/2;

	changeFormatOfTimeForDisplay(emptySlotVector);

	ostringstream toUser;
	toUser << numberEmptySlots << " empty slots found." <<endl;
	for (int i = 0; i < numberEmptySlots; i++) {
			toUser << "Slot " << i+1 << ": " << endl << "	from : " << emptySlotVector[2*i] << endl << "	to   : " << emptySlotVector[2*i+1] << endl << endl;
	}

	return toUser.str();
}

void Logic::changeFormatOfTimeForDisplay (vector<string> &timeFromStorage) {
	for (int i = 0; i < timeFromStorage.size(); i++) {
		timeFromStorage[i].at(13) = ':';
		timeFromStorage[i] = timeFromStorage[i].substr(0, 16);
	}
}

string Logic::printTaskInfo(vector<string> taskDetails) {
	ostringstream toUser;

	toUser << "==================================================================" << endl;
	//toUser << "Task Id	  : " << i << endl;
	toUser << "Task Name	: " << taskDetails[TASK_NAME] << endl;
	toUser << "Start Time	: " << taskDetails[START_TIME] << endl;
	toUser << "End Time	: " << taskDetails[END_TIME] << endl;
	toUser << "Venue		: " << taskDetails[LOCATION] << endl;
	toUser << "Status		: " << taskDetails[STATUS] << endl;
	toUser << "==================================================================" << endl <<endl;

	return toUser.str();
}


//*******************************************************************
//@author A0103459H
// UNDO COMMAND IMPLEMENTATION

int Logic::executeUndoRedo(string inputString, string *output, string *tempUndoCommand) {
	int returnFlag = STATUS_CODE_SET_OVERALL::OVERALL_EXIT;
	string command;

	vector<string> input = getTaskDetails(inputString, &command, &returnFlag);

	COMMAND_TYPE commandType = determineCommand(command);

		switch(commandType) {
	// Undoable functions
		case ADD_TASK:			//can undo
			returnFlag = add(input, output, tempUndoCommand);
			break;
		case DELETE_TASK:		//can undo
			returnFlag = deleter(input, output, tempUndoCommand);
			break;
		case RENAME_TASK:		// can undo
			returnFlag = rename(input, output, tempUndoCommand);
			break;
		case RESCHEDULE_TASK:	//can undo		
			returnFlag = reschedule(input, output, tempUndoCommand);
			break;
		case RELOCATE_TASK:		//can undo
			returnFlag = relocate(input, output, tempUndoCommand);
			break;
		case MARK_TASK:			//can undo
			returnFlag = markTask(input, output, tempUndoCommand);
			break;
		case UNMARK_TASK:		// can undo
			returnFlag = unmarkTask(input, output, tempUndoCommand);
			break;
		case INVALID_ERROR:
			returnFlag = invalid();
			break;
		default:
			returnFlag = invalid();
			break;
		}

	_storage.saveFile();

	return returnFlag;
}

int Logic::undo(string *output) {
	string tempOutputToDump, tempUndoCommand ="";
	int returnFlag;

	if (!undoCommands.empty()) {
		returnFlag = executeUndoRedo(undoCommands.top(), output, &tempUndoCommand);
		undoCommands.pop();

		if (tempUndoCommand != "") {
			redoCommands.push(tempUndoCommand);
		}
		if((returnFlag >= STATUS_CODE_SET_SUCCESS::SUCCESS_ADD) && (returnFlag <= STATUS_CODE_SET_SUCCESS:: SUCCESS_UNMARK)) {
			returnFlag = SUCCESS_UNDO;
		} else {
			returnFlag = ERROR_UNDO;
		}
	} else {
		returnFlag = WARNING_UNDO_NO_COMMAND;			
	}
	return returnFlag;
}

int Logic::redo(string *output) {
	string tempOutputToDump, tempUndoCommand ="";
	int returnFlag;

	if (!redoCommands.empty()) {
		returnFlag = executeUndoRedo(redoCommands.top(), output, &tempUndoCommand);
		redoCommands.pop();
		
		if((returnFlag >= STATUS_CODE_SET_SUCCESS::SUCCESS_ADD) && (returnFlag <= STATUS_CODE_SET_SUCCESS:: SUCCESS_UNMARK)) {
			undoCommands.push(tempUndoCommand);
			returnFlag = SUCCESS_REDO;
		} else {
			returnFlag = ERROR_REDO;
		}

	} else {
		returnFlag = WARNING_REDO_NO_COMMAND;
	}		
	
	return returnFlag;
}

string Logic::undoCommandForAdd (string taskName) {
	string outCommand = COMMAND_DELETE + SPACE + taskName;
	return outCommand;
}

string Logic::undoCommandForDelete (vector<string> taskDetails) {
	string outCommand = COMMAND_ADD + SPACE + taskDetails[TASK_NAME];

	outCommand += SPACE + IDENTIFIER_START_TIME + SPACE + taskDetails[START_TIME];
	outCommand += SPACE + IDENTIFIER_END_TIME_TO + SPACE + taskDetails[END_TIME];
	outCommand += SPACE + IDENTIFIER_VENUE + SPACE + taskDetails[LOCATION];

/*
	if (taskName[START_TIME] != "") {
		outCommand = SPACE + "from" + SPACE + taskDetails[START_TIME];
	}

	if (taskName[END_TIME] != "") {
		outCommand = SPACE + "to" + SPACE + taskDetails[END_TIME];
	}

	if (taskName[LOCATION] != "") {
		outCommand = SPACE + "@" + SPACE + taskDetails[LOCATION];
	}
*/
	return outCommand;

}

string Logic::undoCommandForRename (string nameBeforeRename, string nameAfterRename) {
	string outCommand = COMMAND_RENAME + SPACE + nameAfterRename + SPACE + IDENTIFIER_RENAME + SPACE + nameBeforeRename; 

		return outCommand;
	}

string Logic::undoCommandForReschedule (vector<string> taskDetailsBeforeReschedule) {

	string outCommand = "";

	if (!taskDetailsBeforeReschedule.empty()) {
		string startTimeBeforeReschedule = taskDetailsBeforeReschedule[START_TIME];
		string endTimeBeforeReschedule = taskDetailsBeforeReschedule [END_TIME];

		if (startTimeBeforeReschedule == "") {
			outCommand = COMMAND_RESCHEDULE + SPACE + taskDetailsBeforeReschedule[TASK_NAME] + SPACE + IDENTIFIER_END_TIME_BY + SPACE + endTimeBeforeReschedule;
		} else {
			outCommand = COMMAND_RESCHEDULE + SPACE + taskDetailsBeforeReschedule[TASK_NAME] + SPACE + IDENTIFIER_START_TIME + SPACE + startTimeBeforeReschedule + SPACE + IDENTIFIER_END_TIME_TO + SPACE + endTimeBeforeReschedule;
		}
	}
	return outCommand;
}

string Logic::undoCommandForRelocate (string taskName, string locationBeforeRelocate) {
	string outCommand = COMMAND_RELOCATE + SPACE + taskName + SPACE + IDENTIFIER_VENUE + SPACE + locationBeforeRelocate;
		return outCommand;
}

string Logic::undoCommandForMark (string taskName) {
	string outCommand = COMMAND_UNMARK + SPACE + taskName;
	return outCommand;
}

string Logic::undoCommandForUnmark (string taskName) {
	string outCommand = COMMAND_MARK + SPACE + taskName;
	return outCommand;
}

string Logic::callDidYouMean(string input) {
	historyCommands.push("MESSAGE_DID_YOU_MEAN");
	int returnFlag;
	returnFlag = _storage.searchKeywords(input, _tempStorage);
	if (returnFlag == SUCCESS_SEARCH) {
		return MESSAGE_DID_YOU_MEAN + _tempStorage[0].getTaskName() + MESSAGE_DID_YOU_MEAN_FOLLOW;
		while (_tempStorage.size() != 1) {_tempStorage.pop_back();}
	} else {
		return "";
	}
}

int Logic::getIndexinInt(string input) {
	//returns 0 as Index if it does not find any match else converts it to int and returns. 
	int index = atoi(input.c_str());
	if (index <= 10) {
			return index;
	} else {
		return 0;
	}
}

string Logic::toLowerString (string input) {
	transform(input.begin(), input.end(), input.begin(), ::tolower);
	return input;
}